package org.budo.dubbo.protocol.http.dispatcher.cometd;

import org.budo.dubbo.protocol.http.BudoDubboHttpProtocol;
import org.budo.dubbo.protocol.http.invocation.BudoDubboRpcInvocation;
import org.budo.dubbo.protocol.http.invocation.adapter.InvocationAdapter;
import org.budo.dubbo.protocol.http.invocation.adapter.ProtocolResponse;
import org.cometd.bayeux.server.ServerChannel;
import org.cometd.bayeux.server.ServerMessage.Mutable;
import org.cometd.bayeux.server.ServerSession;

import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.alibaba.dubbo.rpc.Exporter;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;

/**
 * @author lmw
 */
public class ServerChannelMessageListener implements ServerChannel.MessageListener {
    private static final Logger log = LoggerFactory.getLogger(ServerChannelMessageListener.class);

    private BudoBayeuxServerFactoryBean budoBayeuxServerFactoryBean;

    public ServerChannelMessageListener(BudoBayeuxServerFactoryBean budoBayeuxServerFactoryBean) {
        this.budoBayeuxServerFactoryBean = budoBayeuxServerFactoryBean;
    }

    @Override
    public boolean onMessage(ServerSession serverSession, ServerChannel channel, Mutable message) {
        if (!BudoBayeuxServerFactoryBean.REQUEST_CHANNEL_NAME.equals(channel.getId())) {
            log.info("onMessage, requestSession=" + serverSession + ", serverChannel=" + channel + ", message=" + message);
            return true;
        }

        CometdProtocolRequest protocolRequest = new CometdProtocolRequest(message);

        InvocationAdapter invocationAdapter = budoBayeuxServerFactoryBean.getInvocationAdapter();
        BudoDubboRpcInvocation invocation = budoBayeuxServerFactoryBean.adaptInvocation(invocationAdapter, protocolRequest);

        BudoDubboHttpProtocol protocol = BudoDubboHttpProtocol.getInstance();
        Exporter<?> exporter = budoBayeuxServerFactoryBean.findInterfaceExporter(invocation, protocol);

        if (null == exporter) {
            log.error("#100 message=" + message + ", invocation=" + invocation + ", exporter=" + exporter);
            return true;
        }

        Invoker<?> invoker = exporter.getInvoker();
        Result result = invoker.invoke(invocation);

        ProtocolResponse protocolResponse = new CometdProtocolResponse(budoBayeuxServerFactoryBean.getBayeuxServer(), serverSession);

        budoBayeuxServerFactoryBean.renderInvokeResult(protocolRequest, protocolResponse, result);
        return true;
    }
}